﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using LinqToBing.Bing.Wrapper.Enums;

namespace LinqToBing.Bing.Wrapper.ExtensionMethods
{
    /// <summary>
    /// Extension Methods used to prepare strings for query and for other parameters
    /// </summary>
    public static class PrepareStringForSearchExt
    {
        #region PrepareStringForSearch
        /// <summary>
        /// Prepare a string for search treatment. The process consists of replacing spaces with "plus" symbol. 
        /// </summary>
        /// <param name="Text">The string to prepare.</param>
        /// <returns>Returns a string with spaces replaced by plus symbol.</returns>
        /// <example>
        /// query to search => "Hello World! This is dotNetCompass!"
        /// function return => "Hello+World!+This+is+dotNetCompass!"
        /// </example>
        public static string PrepareStringForSearch(this string Text)
        {
            return HttpUtility.UrlEncodeUnicode(Text.Replace(' ', '+'));
        }
        public static string PrepareStringForSearch(this object obj)
        {
            return obj.ToString().PrepareStringForSearch();
        }        
        /// <summary>
        /// Prepare a string array for search treatment. The process consists of replacing spaces with "plus" symbol. 
        /// </summary>
        /// <param name="Text">The string array to prepare.</param>
        /// <returns>Returns a single string with spaces replaced by plus symbol.</returns>
        /// <remarks>The process in this overload is related to search queries, 
        /// in which the spaces is required to be replaced by "plus" symbol.</remarks>
        /// <example>
        /// query to search => "Hello World! This is dotNetCompass!"
        /// function return => "Hello+World!+This+is+dotNetCompass!"
        /// </example>
        public static string PrepareStringForSearch(this string[] Texts)
        {
            StringBuilder Result = new StringBuilder();
            Texts.ToList<string>().ForEach(Text =>
                Result.Append(Text.PrepareStringForSearch())
                );
            return Result.ToString();
        }

        public static string PrepareStringForSearch(this SearchTypeContainer[] container)
        { 
            StringBuilder Result = new StringBuilder();
            Result.Append(container.GetSourcesPreparedForSearch());
            container.ToList<SearchTypeContainer>().ForEach(cont => { Result.TryToAppend(cont.Count); });
            return Result.ToString();
        }

        /// <summary>
        /// Try to append a nullable int value to a StringBuilder instance.
        /// </summary>
        /// <param name="sb">StringBuilder instance to append to.</param>
        /// <param name="value">Nullable int instance to append.</param>
        /// <returns>If nullable int has a value that represents an positive integer, this is append as a "prepared" string to the StringBuilder.</returns>
        private static StringBuilder TryToAppend(this StringBuilder sb, int? value)
        {
            return sb.Append(value.IsPositiveInteger() ? value.Value.PrepareStringForSearch() : string.Empty);
        }
        /// <summary>
        /// Verify if nullable int is a positive integer.
        /// </summary>
        /// <param name="value">Nullable int to check.</param>
        /// <returns>Returns true if nullable int has a value that represents a positive integer.</returns>
        private static bool IsPositiveInteger(this int? value)
        {
            return value.HasValue && (value.Value > 0);
        }

        /// <summary>
        /// Prepare a string array for search treatment.
        /// </summary>
        /// <param name="Text">The string array to prepare.</param>
        /// <returns>Returns a single string with spaces replaced by plus symbol.</returns>
        /// <remarks>The process in this overload is related to search sources to chain with plus symbol 
        /// (if more than one source is required).</remarks>
        /// <example>
        /// sources to search on => { Web, Image }
        /// function return      => "Web+Image"
        /// </example>
        public static string PrepareStringForSearch(this SearchSource[] Searches)
        {
            return Searches.ToList<SearchSource>().PrepareStringForSearch();
        }
        public static string PrepareStringForSearch(this List<SearchSource> Searches)
        {
            StringBuilder Result = new StringBuilder();
            Searches.ForEach(search =>
                {
                    Result.Append((Result.Length>0)?"+":string.Empty);
                    Result.Append(search.PrepareStringForSearch());
                });
            return Result.ToString();
        }        
        #endregion

        /// <summary>
        /// Prepare source list for search treatment.
        /// </summary>
        /// <param name="container">The search type container array to prepare.</param>
        /// <returns>Returns a single string with spaces replaced by plus symbol.</returns>
        public static string GetSourcesPreparedForSearch(this SearchTypeContainer[] container)
        {
            return container.Select(set => set.SearchSource).Cast<SearchSource>().ToArray<SearchSource>().PrepareStringForSearch();
        }

        public static List<SearchSource> GetSearchTypes(this SearchTypeContainer[] container)
        {
            List<SearchSource> Result = new List<SearchSource>();
            container.ToList<SearchTypeContainer>().ForEach( cont =>
                {
                    Result.Add(cont.SearchSource);
                });
            return Result;
        }
    }
}
